<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Document</title>
</head>
<body>
    
</body>
</html>
<script >
// 1.是否存在变量提升？
            // 1.var声明的变量存在变量提升（将变量提升到当前作用域的顶部）。即变量可以在声明之前调用，值为undefined。
            // let和const不存在变量提升。即它们所声明的变量一定要在声明后使用，否则报ReferenceError错。

            console.log(a) //undefined
            var a = 1 ;

            console.log(b) //ReferenceError: g is not defined
            let b = 2;

            console.log(c) //ReferenceError: g is not defined
            const c = 2;

// 2.是否存在暂时性死区？
            // 2.let和const存在暂时性死区。即只要块级作用域内存在let命令，它所声明的变量就“绑定”（binding）这个区域，
            // 不再受外部的影响
            var tmp = 123;
            if (true) {
            tmp = 'abc'; // ReferenceError
            let tmp;
            }
//以上代码if后面{}形成了块级作用域，由于使用let声明了tmp，则这个变量就绑定了块区域，在声明之前使用，会报错。

// 3.是否允许重复声明变量？
            // 3.var允许重复声明变量。
            // let和const在同一作用域不允许重复声明变量。
            var f = 4;
            var f = 5;
            console.log(5) //5

            let g = 6;
            let g = 7;
            console.log(7) //SyntaxError: Identifier 'g' has already been declared

            const h = 8;
            const h = 9;
            console.log(h) //SyntaxError: Identifier 'g' has already been declared

// 4.是否存在块级作用域？
                // 4.var不存在块级作用域。
                // let和const存在块级作用域。
                //1,内层变量可能覆盖外层变量的问题
            var a = 2;
            function fun(){
                console.log(a) //undefined
                if(false){
                    var a = 3;//变量提升带来的，尽管存在块级作用域，但是var声明的变量会跨越这个域。
                }
            }
            fun()
            //2,用来计数的循环变量泄露为全局变量。
            var s = 'hello';
            for (var i = 0; i < s.length; i++) {
            console.log(s[i]);
            }

// 5. 是否能修改声明的变量？
                // var和let可以。
                // const声明一个只读的常量。一旦声明，常量的值就6不能改变。const声明的变量不得改变值，这意味着，
                // const一旦声明变量，就必须立即初始化，不能留到以后赋值。
                const f = 10;
                // f= 11;
                // console.log(f) //报错 不能进行重复声明

                    const obj = {
                        name: '小明',
                        age: 18
                    }
                    obj.age = 20
                    console.log(obj) //{ name: '小明', age: 20 }  
                    //const声明常量，不允许对变量重新赋值。对于引用类型的值而言，只要在栈内存保存的地址值不变即可。

    
</script>